

import { updaterQueue } from './Component'

/**
 *为document绑定事件
 *
 * @export
 * @param {*} dom 真实dom元素
 * @param {*} eventType 事件类型 onclick
 * @param {*} handler  react事件函数
 */
export function addEvent(dom, eventType, handler) {
    let store = dom.store || (dom.store = {})
    store[eventType] = handler // 将事件处理函数暂存在store上
    if (!dom[eventType]) {
        dom[eventType] = dispatchEvent
    }

}
/**
 *  合成事件
 * @param {*} event 
 * target 事件源 永远不变
 * currentTarget  模拟冒泡时的元素  每次递归currentTarget的父元素
 */
function dispatchEvent(event) {
    updaterQueue.isBatchingUpdate = true // 用户事件执行前将是都批量更新设置为true
    const { type, target } = event
    const syntheticEvent = createSyntheticEvent(event)
    let currentTarget = target
    while (currentTarget) {  // 递归模拟事件冒泡
        const eventType = `on${type}`
        const { store } = currentTarget
        let handler = store && store[eventType]
        handler && handler(syntheticEvent) // 真实事件触发时调用 store的对应类型的事件处理函数
        if (syntheticEvent.isPropagationStopped) { //如果用户阻止了默认事件
            break
        }
        currentTarget = currentTarget.parentNode
    }
    updaterQueue.batchUpdate()  // 调用批量更新的方法

    updaterQueue.isBatchingUpdate = false
}

/**
 * 合成事件  兼容不同浏览器事件对象
 * @param {*} event 原生事件对象
 */
function createSyntheticEvent(nativeEvent) {
    let syntheticEvent = {};
    for (let key in nativeEvent) {
        let value = nativeEvent[key]
        if (typeof value === 'function') value = value.bind(nativeEvent)
        syntheticEvent[key] = nativeEvent[key]
    }
    syntheticEvent.nativeEvent = nativeEvent
    syntheticEvent.isDefaultPrevented = false
    syntheticEvent.isPropagationStopped = false
    syntheticEvent.preventDefault = preventDefault // 阻止浏览器默认行为
    syntheticEvent.stopPropagation = stopPropagation // 阻止浏览器冒泡
    return syntheticEvent
}

function preventDefault() {
    this.defaultPrevented = true
    const event = this.nativeEvent
    if (event.preventDefault) {
        event.preventDefault()
    } else {
        event.returnValue = false
    }
    this.isDefaultPrevented = true
}

function stopPropagation() {
    const event = this.nativeEvent
    if (event.stopPropagation) {
        event.stopPropagation()
    } else {
        event.cancelBubble = false
    }
    this.isPropagationStopped = true
}